/**
 * @Title: PointServiceImpl
 * @Package cn.com.yiqi.wsc.service.point.impl
 * @Description: TODO
 * Copyright: Copyright (c) 2016
 * Company: 成都壹柒互动科技有限公司
 * @author 会员系统组-胥钰淋
 * @date 2017/2/9 17:33
 * @version V1.0
 */
package cn.com.yiqi.wsc.service.point.impl;

import cn.com.artemis.framework.service.message.enumeration.SMSOperator;
import cn.com.artemis.framework.service.message.factory.SMSFactory;
import cn.com.yiqi.wsc.common.Result;
import cn.com.yiqi.wsc.common.ResultUtil;
import cn.com.yiqi.wsc.dao.point.PointFetchMapper;
import cn.com.yiqi.wsc.dao.point.PointLogDao;
import cn.com.yiqi.wsc.dao.point.PointRecordDao;
import cn.com.yiqi.wsc.dao.point.entity.PointFetch;
import cn.com.yiqi.wsc.dao.point.entity.PointLogEntity;
import cn.com.yiqi.wsc.dao.point.entity.PointRecordEntity;
import cn.com.yiqi.wsc.entity.customer.Customer;
import cn.com.yiqi.wsc.enumeration.*;
import cn.com.yiqi.wsc.service.customer.CustomerService;
import cn.com.yiqi.wsc.service.point.PointService;
import cn.com.yiqi.wsc.service.point.dataobject.PointInfoDO;
import cn.com.yiqi.wsc.service.point.dataobject.PointOrderDO;
import cn.com.yiqi.wsc.service.point.dataobject.QueryPointDO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author 会员系统组-胥钰淋
 * @ClassName: PointServiceImpl
 * @Description: TODO
 * @date 2017/2/9 17:33
 */
@Service
public class PointServiceImpl implements PointService {

    @Autowired
    private PointRecordDao pointRecordDao;
    @Autowired
    private PointLogDao pointLogDao;

    @Autowired
    private PointFetchMapper pointFetchDao;

    @Autowired
    CustomerService customerService;
    private static final int POINT_INVALID_TIME = 1;

    private List<Integer> getPointBizTypeList() {
        List<Integer> list = new ArrayList<>();
        list.add(PointBizType.deal_get.getValue());
        list.add(PointBizType.deal_refund.getValue());
        list.add(PointBizType.lottery_get.getValue());
        list.add(PointBizType.sys_send.getValue());
        list.add(PointBizType.spread_sale_get.getValue());
        return list;
    }


    @Override
    public PageInfo<PointRecordEntity> queryPointRecord(QueryPointDO query) {
        PageHelper.startPage(query.getCurrentPage(), query.getPageSize());
        Integer status = null;
        if (null != query.getStatus()) {
            status = query.getStatus().getValue();
        }
        Integer type = null;
        if (null != query.getType()) {
            type = query.getType().getValue();
        }
        List<PointRecordEntity> pointRecordEntityList = pointRecordDao.selectList(query.getCustomerId(), type, status, null, null);
        PageInfo<PointRecordEntity> pageInfo = new PageInfo<>(pointRecordEntityList);
        return pageInfo;
    }

    @Override
    public List<PointRecordEntity> findAvailablePointRecord(long customerId, Date invalidTime) {

        List<PointRecordEntity> pointRecordEntityList = pointRecordDao.selectList(customerId, null, PointStatus.usable.getValue(), invalidTime, getPointBizTypeList());
        return pointRecordEntityList;
    }


    private Result<Long> pointRecord(PointOrderDO pointOrderDO) {
        Result<Long> result = new Result<>();
        Customer customer = customerService.selectById(pointOrderDO.getCustomerId().intValue());
        PointOperateTypeEnum operate = setPointOperatType(pointOrderDO.getType());
        if(operate == PointOperateTypeEnum.DECREASE && customer.getPoint() < pointOrderDO.getPoint()){
            return ResultUtil.fail(result,"积分不足");
        }
        PointRecordEntity pre = new PointRecordEntity();
        pre.setPoint(pointOrderDO.getPoint());
        pre.setBizType(pointOrderDO.getType().getValue());
        pre.setOperateType(operate.getValue());
        pre.setBizDesc(pointOrderDO.getBizDesc());
        pre.setCustomerId(pointOrderDO.getCustomerId());
        pre.setInsertTime(new Date());
        pointRecordDao.insert(pre);
        if(!pointOrderDO.getHasDeal()){
            Integer customerPoint = customer.getPoint()==null?0:customer.getPoint();
            if(operate == PointOperateTypeEnum.ADD){
                customer.setPoint(customerPoint + pointOrderDO.getPoint());
            }else {
                customer.setPoint(customerPoint - pointOrderDO.getPoint());
            }
            customerService.updateCustomer(customer);
        }
        result.setReturnValue(pre.getId());
        return result;
    }

    /**
     * 设置操作类型(增加积分还是扣积分)
     */
    private PointOperateTypeEnum setPointOperatType(PointBizType bizType) {

        if (bizType == PointBizType.deal_use
                || bizType == PointBizType.lottery_use
                || bizType == PointBizType.exchange_to_balance) {
            return PointOperateTypeEnum.DECREASE;
        } else {
            return  PointOperateTypeEnum.ADD;
        }
    }


    @Override
    public Result<Long> grantPoint(PointOrderDO pointOrderDO) {
        pointOrderDO.setType(PointBizType.deal_get);
        return pointRecord( pointOrderDO);
    }

    @Override
    public Result<Long> givePoint(PointOrderDO pointOrderDO) {
        pointOrderDO.setType(PointBizType.sys_send);
        return pointRecord( pointOrderDO);
    }

    @Override
    public Result<Long> singGetPoint(PointOrderDO pointOrderDO) {
        pointOrderDO.setType(PointBizType.sign_get);
        return pointRecord( pointOrderDO);
    }

    @Override
    public Result<Long> dealUse(PointOrderDO pointOrderDO) {
        pointOrderDO.setType(PointBizType.deal_use);
        return pointRecord( pointOrderDO);
    }

    @Override
    public Result<Long> spreadGet(PointOrderDO pointOrderDO) {
        pointOrderDO.setType(PointBizType.spread_sale_get);
        return pointRecord( pointOrderDO);
    }

    @Transactional
    @Override
    public Result extraPointApply(Integer userId, Integer exchangePoint) {
        Result re = new Result();
        //冻结积分
        PointOrderDO pdo = new PointOrderDO();
        pdo.setType(PointBizType.exchange_to_balance);
        pdo.setBizDesc("兑换余额");
        pdo.setPoint(exchangePoint);
        pdo.setCustomerId(Long.parseLong(userId+""));
        Long bizId = pointRecord(pdo).getReturnValue();

        PointFetch fetch = new PointFetch();
        fetch.setCustomerId(userId);
        fetch.setPoint(exchangePoint);
        fetch.setStatus(Byte.parseByte(PointFetchType.wait_verify.getValue() + ""));
        fetch.setApplyTime(new Date());
        fetch.setPointRecordId(bizId.intValue());
        pointFetchDao.insertSelective(fetch);
        return ResultUtil.success(re);
    }

    @Override
    public Result extraPointApplyRecord(Integer userId) {
        Result re = new Result();
        List<PointFetch> list = pointFetchDao.selectByUserId(userId);
        re.putData("list", list);
        return re;
    }

    @Override
    public Result<Long> lotteryGetPoint(PointOrderDO pointOrderDO) {
        pointOrderDO.setType(PointBizType.lottery_get);
        return pointRecord( pointOrderDO);

    }

    @Override
    public Result<Long> lotteryUsePoint(PointOrderDO pointOrderDO) {
        pointOrderDO.setType(PointBizType.lottery_use);
        return pointRecord( pointOrderDO);

    }

    @Override
    public Result<Boolean> returnCostPoint(PointOrderDO pointOrderDO) {
        return null;
    }

    @Override
    public Result<Boolean> refundCostPoint(PointOrderDO pointOrderDO) {
        return null;
    }

    @Override
    public Result<Boolean> lotteryCostPoint(PointOrderDO pointOrderDO) {
        return null;
    }

    @Override
    public Result<Long> point2Balance(PointOrderDO pointOrderDO) {
        pointOrderDO.setType(PointBizType.exchange_to_balance);
        return pointRecord( pointOrderDO);

    }

    @Override
    public Long getPoint2BalanceTotalAmount(Long customerId, Date from, Date to, Integer type) {
        Long amount = pointRecordDao.sumExchangePoint(customerId, from, to, type);
        if (amount == null) {
            return 0L;
        }
        return amount;
    }

    @Override
    public Long getPoint2BalanceTotalTims(Long customerId, Date from, Date to, Integer type) {
        Long times = pointRecordDao.countExchangePoint(customerId, from, to, type);
        if (times == null) {
            return 0L;
        }
        return times;
    }

}
